﻿using System.Security.Claims;
using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Validation;

namespace Ids4.Server;

public class RefreshTokenService : IRefreshTokenService
{
    /// <summary>
    /// 模拟RefreshToken存在缓存中
    /// </summary>
    private readonly static Dictionary<string, RefreshToken> _refreshTokens = new Dictionary<string, RefreshToken>();

    /// <summary>
    /// 创建刷新token
    /// </summary>
    /// <param name="subject"></param>
    /// <param name="accessToken"></param>
    /// <param name="client"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<string> CreateRefreshTokenAsync(ClaimsPrincipal subject, Token accessToken, Client client)
    {
        var handle = Guid.NewGuid().ToString();
        var refreshToken = new RefreshToken
        {
            AccessToken = accessToken,
            CreationTime = DateTime.UtcNow,
            Lifetime = client.RefreshTokenExpiration == TokenExpiration.Sliding ? client.SlidingRefreshTokenLifetime : client.AbsoluteRefreshTokenLifetime,
            //Subject = subject,
            Version = 1
        };
        _refreshTokens[handle] = refreshToken;
        return await Task.FromResult(handle);
    }

    /// <summary>
    /// 修改刷新token
    /// </summary>
    /// <param name="handle"></param>
    /// <param name="refreshToken"></param>
    /// <param name="client"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<string> UpdateRefreshTokenAsync(string handle, RefreshToken refreshToken, Client client)
    {
        if (!_refreshTokens.ContainsKey(handle))
        {
            throw new ArgumentException("Invalid refresh token handle");
        }

        _refreshTokens[handle] = refreshToken;
        return await Task.FromResult(handle);
    }

    /// <summary>
    /// 验证刷新token
    /// </summary>
    /// <param name="token"></param>
    /// <param name="client"></param>
    /// <returns></returns>
    /// <exception cref="NotImplementedException"></exception>
    public async Task<TokenValidationResult> ValidateRefreshTokenAsync(string token, Client client)
    {
        if (!_refreshTokens.TryGetValue(token, out var refreshToken))
        {
            return await Task.FromResult(new TokenValidationResult
            {
                IsError = true,
                Error = "Invalid refresh token"
            });
        }

        if (refreshToken.AccessToken.ClientId != client.ClientId)
        {
            return await Task.FromResult(new TokenValidationResult
            {
                IsError = true,
                Error = "Refresh token does not belong to the client"
            });
        }

        if (DateTime.UtcNow > refreshToken.CreationTime.AddSeconds(refreshToken.Lifetime))
        {
            return await Task.FromResult(new TokenValidationResult
            {
                IsError = true,
                Error = "Refresh token has expired"
            });
        }

        return await Task.FromResult(new TokenValidationResult
        {
            IsError = false,
            RefreshToken = refreshToken
        });
    }
}